﻿#region File and License Information
/*
<File>
	<License>
		Copyright © 2009 - 2017, Daniel Vaughan. All rights reserved.
		This file is part of Calcium (http://calciumsdk.net), 
		which is released under the MIT License.
		See file /Documentation/License.txt for details.
	</License>
	<CreationDate>2013-01-01 11:32:08Z</CreationDate>
</File>
*/
#endregion

using System;
using System.Windows;
using Outcoder.Net;
using Windows.Networking.Connectivity;

#if WINDOWS_UWP || NETFX_CORE
using System.Net.NetworkInformation;
#else
using Microsoft.Phone.Net.NetworkInformation;
#endif

namespace Outcoder.Services.Implementation
{
	public class NetworkMonitoringService : INetworkMonitoringService
	{
		const int DefaultSampleRateMs = 1000;

		int sampleRateMs;

		public int SampleRateMs
		{
			get
			{
				return sampleRateMs;
			}
		}

		public bool ApproachingDataLimit { get; private set; }

		public bool Roaming { get; private set; }

		public virtual bool LimitData
		{
			get
			{
				return Roaming || ApproachingDataLimit;
			}
		}

		public NetworkConnectionType NetworkConnectionType  { get; private set; }
		public event EventHandler<EventArgs> NetworkConnectionChanged;

		public bool Connected
		{
			get
			{
#if WINDOWS_UWP
				return NetworkInterface.GetIsNetworkAvailable();
#else
			return NetworkInterface.GetIsNetworkAvailable();
#endif
			}
		}

		public NetworkMonitoringService(int sampleRateMs = DefaultSampleRateMs)
		{
			this.sampleRateMs = sampleRateMs;

			Update();

			NetworkInformation.NetworkStatusChanged += HandleNetworkStatusChanged;
		}

		void HandleNetworkStatusChanged(object sender)
		{
			Update();
#if WINDOWS_UWP
			UISynchronizationContext.Instance.InvokeIfRequired(() =>
#else
			Deployment.Current.Dispatcher.InvokeIfRequired(() =>
#endif
			{
					NetworkConnectionChanged?.Invoke(this, EventArgs.Empty);

					IMessenger messenger;
					if (Dependency.TryResolve<IMessenger>(out messenger))
					{
						messenger.Publish(new NetworkAvailabilityChangedMessage(
							new NetworkConnectionInfo(NetworkConnectionType, LimitData)));
					}
				});
		}

		public void Update()
		{
			ConnectionProfile profile = NetworkInformation.GetInternetConnectionProfile();

			if (profile == null)
			{
				NetworkConnectionType = Connected ? NetworkConnectionType.Lan : NetworkConnectionType.None;
			}
			else
			{
				ConnectionCost cost = profile.GetConnectionCost();
				ApproachingDataLimit = cost.ApproachingDataLimit;
				Roaming = cost.Roaming;

				uint interfaceType = profile.NetworkAdapter.IanaInterfaceType;

				if (interfaceType == 71)
				{
					NetworkConnectionType = NetworkConnectionType.Lan;
				}
				else if (interfaceType == 6)
				{
					NetworkConnectionType = NetworkConnectionType.Lan;
				}
				else
				{
					NetworkConnectionType = NetworkConnectionType.MobileBroadband;
				}
			}
		}

		public string Ssid
		{
			get
			{
#if !WINDOWS_UWP
				foreach (var network in new NetworkInterfaceList())
				{
					if ((network.InterfaceType == NetworkInterfaceType.Wireless80211) &&
						(network.InterfaceState == ConnectState.Connected))
					{
						return network.InterfaceName;
					}
				}
#endif
				return null;
			}
		}
	}
}
